Emit changed and notify:text only once. The same fix was applied for
authorMatthias Clasen <mclasen@redhat.com>
Sun, 24 Dec 2006 05:18:25 +0000 (05:18 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Sun, 24 Dec 2006 05:18:25 +0000 (05:18 +0000)
2006-12-24  Matthias Clasen  <mclasen@redhat.com>

        * gtk/gtkentry.c (gtk_entry_set_text): Emit changed
        and notify:text only once. The same fix was applied
        for replacing the selection via DND or copy-and-paste.
        (#64998, Damon Chaplin, Sven Herzberg)

ChangeLog
gtk/gtkentry.c

index 330bbe9c18c063afff2318cc313db27789bbd958..5be897ebd22abc3706e34a31838bb88737c4d88a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-12-24  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtkentry.c (gtk_entry_set_text): Emit changed
+       and notify:text only once. The same fix was applied
+       for replacing the selection via DND or copy-and-paste.
+       (#64998, Damon Chaplin, Sven Herzberg)
+
 2006-12-23  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkimmulticontext.c: Be careful to not override
index 011ee01ba12859b86897884edd877db1a2bcd6a4..b81d3e335db3e3cd8a89050883c937d713e2aaef 100644 (file)
@@ -83,6 +83,8 @@ struct _GtkEntryPrivate
   gfloat xalign;
   gint insert_pos;
   guint blink_time;  /* time in msec the cursor has blinked since last user event */
+  guint real_changed : 1;
+  guint change_count : 8;
 };
 
 typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
@@ -369,6 +371,9 @@ static void         disconnect_completion_signals      (GtkEntry           *entr
 static void         connect_completion_signals         (GtkEntry           *entry,
                                                        GtkEntryCompletion *completion);
 
+static void         begin_change                       (GtkEntry *entry);
+static void         end_change                         (GtkEntry *entry);
+static void         emit_changed                       (GtkEntry *entry);
 
 G_DEFINE_TYPE_WITH_CODE (GtkEntry, gtk_entry, GTK_TYPE_WIDGET,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE,
@@ -1091,6 +1096,46 @@ gtk_entry_init (GtkEntry *entry)
                    G_CALLBACK (gtk_entry_delete_surrounding_cb), entry);
 }
 
+static void
+begin_change (GtkEntry *entry)
+{
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  priv->change_count++;
+}
+
+static void
+end_change (GtkEntry *entry)
+{
+  GtkEditable *editable = GTK_EDITABLE (entry);
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+  g_return_if_fail (priv->change_count > 0);
+
+  priv->change_count--;
+
+  if (priv->change_count == 0)
+    {
+       if (priv->real_changed) 
+         {
+           g_signal_emit_by_name (editable, "changed");
+           priv->real_changed = FALSE;
+         }
+    } 
+}
+
+static void
+emit_changed (GtkEntry *entry)
+{
+  GtkEditable *editable = GTK_EDITABLE (entry);
+  GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+
+  if (priv->change_count == 0)
+    g_signal_emit_by_name (editable, "changed");
+  else 
+    priv->real_changed = TRUE;
+}
+
 /*
  * Overwrite a memory that might contain sensitive information.
  */
@@ -2432,7 +2477,7 @@ gtk_entry_real_insert_text (GtkEditable *editable,
 
   gtk_entry_recompute (entry);
 
-  g_signal_emit_by_name (editable, "changed");
+  emit_changed (entry);
   g_object_notify (G_OBJECT (editable), "text");
 }
 
@@ -2482,7 +2527,7 @@ gtk_entry_real_delete_text (GtkEditable *editable,
       
       gtk_entry_recompute (entry);
 
-      g_signal_emit_by_name (editable, "changed");
+      emit_changed (entry);
       g_object_notify (G_OBJECT (editable), "text");
     }
 }
@@ -4020,12 +4065,16 @@ paste_received (GtkClipboard *clipboard,
             g_signal_handler_block (entry, completion->priv->changed_id);
        }
 
+      begin_change (entry);
+      g_object_freeze_notify (G_OBJECT (entry));
       if (gtk_editable_get_selection_bounds (editable, &start, &end))
         gtk_editable_delete_text (editable, start, end);
 
       pos = entry->current_pos;
       gtk_editable_insert_text (editable, text, length, &pos);
       gtk_editable_set_position (editable, pos);
+      g_object_thaw_notify (G_OBJECT (entry));
+      end_change (entry);
 
       if (completion &&
           !popup_completion && completion->priv->changed_id > 0)
@@ -4178,10 +4227,14 @@ gtk_entry_set_text (GtkEntry    *entry,
   if (completion && completion->priv->changed_id > 0)
     g_signal_handler_block (entry, completion->priv->changed_id);
 
+  begin_change (entry);
+  g_object_freeze_notify (G_OBJECT (entry));
   gtk_editable_delete_text (GTK_EDITABLE (entry), 0, -1);
 
   tmp_pos = 0;
   gtk_editable_insert_text (GTK_EDITABLE (entry), text, strlen (text), &tmp_pos);
+  g_object_thaw_notify (G_OBJECT (entry));
+  end_change (entry);
 
   if (completion && completion->priv->changed_id > 0)
     g_signal_handler_unblock (entry, completion->priv->changed_id);
@@ -5183,8 +5236,12 @@ gtk_entry_drag_data_received (GtkWidget        *widget,
       else
        {
          /* Replacing selection */
+          begin_change (entry);
+          g_object_freeze_notify (G_OBJECT (entry));
          gtk_editable_delete_text (editable, sel1, sel2);
          gtk_editable_insert_text (editable, str, length, &sel1);
+          g_object_thaw_notify (G_OBJECT (entry));
+          end_change (entry);
        }
       
       gtk_drag_finish (context, TRUE, context->action == GDK_ACTION_MOVE, time);